/*
 * Copyright 2018 dc-square GmbH
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 * http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 *
 */

package com.hivemq.extensions.rbac.configuration;

import com.hivemq.extensions.rbac.configuration.entities.*;
import com.hivemq.extension.sdk.api.annotations.NotNull;

import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import java.util.Set;

/**
 * 配置凭据验证器
 */
public class ConfigCredentialsValidator {

    @NotNull
    public static ValidationResult validateConfig(@NotNull final ExtensionConfig extensionConfig, @NotNull final FileAuthConfig config) {

        final List<String> errors = new ArrayList<>();
        boolean validationSuccessful = true;

        final List<User> users = config.getUsers();
        final List<Role> roles = config.getRoles();
        if (users == null || users.isEmpty()) {
            errors.add("在配置文件中找不到用户");
            validationSuccessful = false;
        }

        if (roles == null || roles.isEmpty()) {
            errors.add("在配置文件中找不到角色");
            validationSuccessful = false;
        }

        // 如果缺少用户或角色，请在此处停止
        if (!validationSuccessful) {
            return new ValidationResult(errors, false);
        }

        Set<String> roleIds = new HashSet<>();

        for (Role role : roles) {
            if (role.getId() == null || role.getId().isEmpty()) {
                errors.add("角色缺少ID");
                validationSuccessful = false;
                continue;
            }

            if (roleIds.contains(role.getId())) {
                errors.add("重复的角色ID: '" + role.getId() + "'");
                validationSuccessful = false;
                continue;
            }

            roleIds.add(role.getId());

            if (role.getPermissions() == null || role.getPermissions().isEmpty()) {
                errors.add("角色 '" + role.getId() + "' 缺少权限");
                validationSuccessful = false;
                continue;
            }

            for (Permission permission : role.getPermissions()) {
                if (permission.getTopic() == null || permission.getTopic().isEmpty()) {
                    errors.add("角色id '" + role.getId() + "' 的许可额缺少主题过滤器");
                    validationSuccessful = false;
                }

                if (permission.getActivity() == null) {
                    errors.add("无效值 Activity in Permission for role with id '" + role.getId() + "'");
                    validationSuccessful = false;
                }

                if (permission.getQos() == null) {
                    errors.add("无效值 for QoS in Permission for role with id '" + role.getId() + "'");
                    validationSuccessful = false;
                }

                if (permission.getRetain() == null) {
                    errors.add("无效值  for Retain in Permission for role with id '" + role.getId() + "'");
                    validationSuccessful = false;
                }

                if (permission.getSharedGroup() == null || permission.getSharedGroup().isEmpty()) {
                    errors.add("无效值  for Shared Group in Permission for role with id '" + role.getId() + "'");
                    validationSuccessful = false;
                }

                if (permission.getSharedSubscription() == null) {
                    errors.add("无效值  for Shared Subscription in Permission for role with id '" + role.getId() + "'");
                    validationSuccessful = false;
                }
            }
        }

        Set<String> userNames = new HashSet<>();

        for (User user : users) {
            if (user.getName() == null || user.getName().isEmpty()) {
                errors.add("用户缺少名称");
                validationSuccessful = false;
                continue;
            }

            if (userNames.contains(user.getName())) {
                errors.add("用户名称重复 '" + user.getName() + "'");
                validationSuccessful = false;
                continue;
            }

            userNames.add(user.getName());

            if (user.getPassword() == null || user.getPassword().isEmpty()) {
                errors.add("用户 '" + user.getName() + "' 缺少密码");
                validationSuccessful = false;
                continue;
            }

            if (extensionConfig.getPasswordType() == PasswordType.HASHED) {

                final String password = user.getPassword();
                final String[] split = password.split(":");

                if (split.length < 2 || split[0].isEmpty() || split[1].isEmpty()) {
                    errors.add("用户 '" + user.getName() + "' 密码无效");
                    validationSuccessful = false;
                    continue;
                }
            }

            if (user.getRoles() == null || user.getRoles().isEmpty()) {
                errors.add("用户 '" + user.getName() + "' 缺少角色");
                validationSuccessful = false;
                continue;
            }

            for (String role : user.getRoles()) {
                if (role == null || role.isEmpty()) {
                    errors.add("用户的角色无效 '" + user.getName() + "'");
                    validationSuccessful = false;
                    continue;
                }

                if (!roleIds.contains(role)) {
                    errors.add("用户角色不明'" + role + "' '" + user.getName() + "'");
                    validationSuccessful = false;
                }
            }
        }

        return new ValidationResult(errors, validationSuccessful);
    }

    /**
     * 验证结果
     */
    public static class ValidationResult {
        private final @NotNull List<String> errors;
        private final boolean validationSuccessful;

        private ValidationResult(@NotNull final List<String> errors, final boolean validationSuccessful) {
            this.errors = errors;
            this.validationSuccessful = validationSuccessful;
        }

        @NotNull
        public List<String> getErrors() {
            return errors;
        }

        public boolean isValidationSuccessful() {
            return validationSuccessful;
        }
    }
}
